use crate::audio_device::{AudioDeviceManager, AudioDeviceError, AudioDeviceInfo, AudioStreamConfig};
use crate::audio_stream::{AudioStreamManager, AudioStreamSettings, AudioQualityMetrics, AudioStreamError};

use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::RwLock;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum AudioManagerError {
    #[error("Audio device error: {0}")]
    DeviceError(String),
    #[error("Audio stream error: {0}")]
    StreamError(String),
    #[error("Device not found: {0}")]
    DeviceNotFound(String),
    #[error("Audio device manager error: {0}")]
    AudioDeviceError(#[from] AudioDeviceError),
    #[error("Audio stream manager error: {0}")]
    AudioStreamError(#[from] AudioStreamError),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AudioDevice {
    pub id: String,
    pub name: String,
    pub is_default: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AudioDevices {
    pub input_devices: Vec<AudioDevice>,
    pub output_devices: Vec<AudioDevice>,
    pub current_input: Option<String>,
    pub current_output: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AudioLevels {
    pub input_level: f32,
    pub output_level: f32,
    pub is_muted: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AudioConfig {
    pub input_device: Option<String>,
    pub output_device: Option<String>,
    pub input_volume: f32,
    pub output_volume: f32,
    pub echo_cancellation: bool,
    pub noise_suppression: bool,
}

pub struct AudioManager {
    device_manager: Arc<AudioDeviceManager>,
    stream_manager: Arc<RwLock<AudioStreamManager>>,
    current_input_device: Arc<RwLock<Option<String>>>,
    current_output_device: Arc<RwLock<Option<String>>>,
    is_muted: Arc<RwLock<bool>>,
    input_level: Arc<RwLock<f32>>,
    output_level: Arc<RwLock<f32>>,
    stream_config: Arc<RwLock<AudioStreamConfig>>,
}

impl AudioManager {
    pub fn new() -> Result<Self, AudioManagerError> {
        let device_manager = Arc::new(AudioDeviceManager::new()?);
        let stream_manager = Arc::new(RwLock::new(AudioStreamManager::new(Arc::clone(&device_manager))));
        
        Ok(Self {
            device_manager,
            stream_manager,
            current_input_device: Arc::new(RwLock::new(None)),
            current_output_device: Arc::new(RwLock::new(None)),
            is_muted: Arc::new(RwLock::new(false)),
            input_level: Arc::new(RwLock::new(0.0)),
            output_level: Arc::new(RwLock::new(0.0)),
            stream_config: Arc::new(RwLock::new(AudioStreamConfig::default())),
        })
    }

    pub async fn get_audio_devices(&self) -> Result<AudioDevices, AudioManagerError> {
        // Enumerate devices using the device manager
        self.device_manager.enumerate_devices().await?;
        
        let input_devices_info = self.device_manager.get_input_devices().await;
        let output_devices_info = self.device_manager.get_output_devices().await;

        // Convert AudioDeviceInfo to AudioDevice
        let input_devices: Vec<AudioDevice> = input_devices_info.into_iter()
            .map(|info| AudioDevice {
                id: info.id,
                name: info.name,
                is_default: info.is_default,
            })
            .collect();

        let output_devices: Vec<AudioDevice> = output_devices_info.into_iter()
            .map(|info| AudioDevice {
                id: info.id,
                name: info.name,
                is_default: info.is_default,
            })
            .collect();

        let current_input = self.current_input_device.read().await.clone();
        let current_output = self.current_output_device.read().await.clone();

        Ok(AudioDevices {
            input_devices,
            output_devices,
            current_input,
            current_output,
        })
    }

    pub async fn set_audio_device(
        &self,
        input_device: Option<String>,
        output_device: Option<String>,
    ) -> Result<(), AudioManagerError> {
        if let Some(input_id) = input_device {
            // Set the device in the device manager
            self.device_manager.set_input_device(&input_id).await?;
            *self.current_input_device.write().await = Some(input_id.clone());
            log::info!("Set input device to: {}", input_id);
        }

        if let Some(output_id) = output_device {
            // Set the device in the device manager
            self.device_manager.set_output_device(&output_id).await?;
            *self.current_output_device.write().await = Some(output_id.clone());
            log::info!("Set output device to: {}", output_id);
        }

        Ok(())
    }

    pub async fn get_audio_levels(&self) -> AudioLevels {
        AudioLevels {
            input_level: *self.input_level.read().await,
            output_level: *self.output_level.read().await,
            is_muted: *self.is_muted.read().await,
        }
    }

    pub async fn set_muted(&self, muted: bool) {
        *self.is_muted.write().await = muted;
        log::info!("Audio muted: {}", muted);
    }

    pub async fn start_audio_stream(&self, call_id: &str) -> Result<(), AudioManagerError> {
        log::info!("Starting audio stream for call: {}", call_id);
        
        let config = self.stream_config.read().await.clone();
        
        // Create input and output streams
        self.device_manager.create_input_stream(config.clone()).await?;
        self.device_manager.create_output_stream(config).await?;
        
        log::info!("Audio streams started successfully for call: {}", call_id);
        Ok(())
    }

    pub async fn stop_audio_stream(&self, call_id: &str) -> Result<(), AudioManagerError> {
        log::info!("Stopping audio stream for call: {}", call_id);
        
        // Stop all streams
        self.device_manager.stop_all_streams().await?;
        
        log::info!("Audio streams stopped successfully for call: {}", call_id);
        Ok(())
    }

    pub async fn set_stream_config(&self, config: AudioStreamConfig) -> Result<(), AudioManagerError> {
        *self.stream_config.write().await = config.clone();
        log::info!("Updated audio stream configuration: {:?}", config);
        Ok(())
    }

    pub async fn get_stream_config(&self) -> AudioStreamConfig {
        self.stream_config.read().await.clone()
    }

    pub async fn get_detailed_audio_devices(&self) -> Result<Vec<AudioDeviceInfo>, AudioManagerError> {
        self.device_manager.enumerate_devices().await?;
        let mut all_devices = Vec::new();
        
        let input_devices = self.device_manager.get_input_devices().await;
        let output_devices = self.device_manager.get_output_devices().await;
        
        all_devices.extend(input_devices);
        all_devices.extend(output_devices);
        
        Ok(all_devices)
    }

    pub async fn update_audio_levels(&self, input_level: f32, output_level: f32) {
        *self.input_level.write().await = input_level.clamp(0.0, 1.0);
        *self.output_level.write().await = output_level.clamp(0.0, 1.0);
    }

    pub async fn get_current_input_device_id(&self) -> Option<String> {
        self.current_input_device.read().await.clone()
    }

    pub async fn get_current_output_device_id(&self) -> Option<String> {
        self.current_output_device.read().await.clone()
    }

    // Audio Stream Management Methods

    pub async fn create_audio_stream(
        &self,
        call_id: String,
        settings: AudioStreamSettings,
    ) -> Result<(), AudioManagerError> {
        let mut stream_manager = self.stream_manager.write().await;
        stream_manager.create_stream(call_id, settings).await?;
        log::info!("Created audio stream for call");
        Ok(())
    }

    pub async fn create_audio_stream_with_quality(
        &self,
        call_id: String,
        settings: AudioStreamSettings,
        quality_settings: crate::audio_stream::AudioQualitySettings,
    ) -> Result<(), AudioManagerError> {
        let mut stream_manager = self.stream_manager.write().await;
        stream_manager.create_stream_with_quality(call_id, settings, quality_settings).await?;
        log::info!("Created audio stream with quality settings for call");
        Ok(())
    }

    pub async fn set_stream_quality_settings(
        &self,
        call_id: &str,
        quality_settings: crate::audio_stream::AudioQualitySettings,
    ) -> Result<(), AudioManagerError> {
        let mut stream_manager = self.stream_manager.write().await;
        stream_manager.set_stream_quality_settings(call_id, quality_settings).await?;
        log::info!("Updated quality settings for call: {}", call_id);
        Ok(())
    }

    pub async fn get_stream_quality_settings(
        &self,
        call_id: &str,
    ) -> Option<crate::audio_stream::AudioQualitySettings> {
        let stream_manager = self.stream_manager.read().await;
        stream_manager.get_stream_quality_settings(call_id).cloned()
    }

    pub async fn start_audio_stream_for_call(&self, call_id: &str) -> Result<(), AudioManagerError> {
        let mut stream_manager = self.stream_manager.write().await;
        stream_manager.start_stream(call_id).await?;
        log::info!("Started audio stream for call: {}", call_id);
        Ok(())
    }

    pub async fn stop_audio_stream_for_call(&self, call_id: &str) -> Result<(), AudioManagerError> {
        let mut stream_manager = self.stream_manager.write().await;
        stream_manager.stop_stream(call_id).await?;
        log::info!("Stopped audio stream for call: {}", call_id);
        Ok(())
    }

    pub async fn process_incoming_rtp(
        &self,
        call_id: &str,
        rtp_packet: rtp::RtpPacket,
    ) -> Result<(), AudioManagerError> {
        let mut stream_manager = self.stream_manager.write().await;
        stream_manager.process_incoming_rtp(call_id, rtp_packet).await?;
        Ok(())
    }

    pub async fn get_outgoing_rtp(&self, call_id: &str) -> Option<rtp::RtpPacket> {
        let mut stream_manager = self.stream_manager.write().await;
        stream_manager.get_outgoing_rtp(call_id).await
    }

    pub async fn set_call_muted(&self, call_id: &str, muted: bool) -> Result<(), AudioManagerError> {
        let stream_manager = self.stream_manager.read().await;
        stream_manager.set_stream_muted(call_id, muted).await?;
        
        // Also update global mute state
        *self.is_muted.write().await = muted;
        log::info!("Set call {} muted: {}", call_id, muted);
        Ok(())
    }

    pub async fn get_call_quality_metrics(&self, call_id: &str) -> Option<AudioQualityMetrics> {
        let stream_manager = self.stream_manager.read().await;
        stream_manager.get_stream_quality_metrics(call_id)
    }

    pub async fn get_active_audio_streams(&self) -> Vec<String> {
        let stream_manager = self.stream_manager.read().await;
        stream_manager.get_active_streams()
    }

    pub async fn update_audio_levels_from_streams(&self) {
        let active_streams = self.get_active_audio_streams().await;
        
        if let Some(call_id) = active_streams.first() {
            if let Some(metrics) = self.get_call_quality_metrics(call_id).await {
                *self.input_level.write().await = metrics.input_level;
                *self.output_level.write().await = metrics.output_level;
            }
        }
    }
}

impl Default for AudioManager {
    fn default() -> Self {
        Self::new().expect("Failed to create AudioManager")
    }
}